package com.platform.framework.web.service.web;


import com.alibaba.fastjson2.JSONObject;
import com.platform.common.constant.Constants;
import com.platform.common.core.domain.AjaxResult;
import com.platform.common.core.domain.entity.WebUser;
import com.platform.common.core.domain.model.LoginUser;
import com.platform.common.core.domain.model.WebLoginUser;
import com.platform.common.core.redis.RedisCache;
import com.platform.common.enums.ResultEnum;
import com.platform.common.exception.BusinessException;
import com.platform.common.exception.user.PhoneCodeNotMatchException;
import com.platform.common.utils.StringUtils;
import com.platform.framework.security.context.AuthenticationContextHolder;
import com.platform.framework.web.service.admin.TokenService;
import com.platform.system.domain.dto.device.WebUserInfoDto;
import com.platform.system.domain.vo.UserCodeVo;
import com.platform.system.domain.vo.device.WebUserInfoVo;
import com.platform.system.logic.SmsCodeLogic;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author Huangkai
 */
@Slf4j
@Component
public class WebUserLoginService {


    @Autowired
    private RedisCache redisCache;

    @Resource
    AuthenticationManager authenticationManager;

    @Resource
    TokenService tokenService;

    @Resource
    SmsCodeLogic smsCodeLogic;


    public AjaxResult getCode(WebUserInfoVo webUserVo) {
        String key = webUserVo.getPhone() + "_" + Constants.CODE;
        if(redisCache.hasKey(key)){
            throw new BusinessException(ResultEnum.GET_CODE_FAIL);
        }
        //获取随机数
        String code = StringUtils.getNumberStr(6);
        UserCodeVo userCodeVo = new UserCodeVo();
        userCodeVo.setZoneDescription(webUserVo.getZone());
        userCodeVo.setPhone(webUserVo.getPhone());
        userCodeVo.setCode(code);
        boolean flag =  smsCodeLogic.sendCode(userCodeVo);
        if(flag){
            //存储到redis中
            redisCache.setCacheObject(key, code, Constants.NUM_ONE, TimeUnit.MINUTES);
            return AjaxResult.success(ResultEnum.GET_CODE_SUCCESS.message);
        }
        throw new BusinessException(ResultEnum.SEND_CODE_FAIL);
    }

    /**
     * 客户端登陆
     * @param webUserVo
     * @return
     */
    public AjaxResult webLogin(WebUserInfoVo webUserVo) {
        //如果是等于1，则校验验证码
        if(webUserVo.getLoginType().equals(Constants.NUM_ZERO)){
            checkPhoneCode(webUserVo);
        }
        //校验微信登陆
        if(webUserVo.getLoginType().equals(Constants.NUM_ONE)){

        }
        // 用户验证
        Authentication authentication = null;
        try {
            Map<String, String> map = new HashMap<>(2);
            map.put("phone", webUserVo.getPhone());
            if(StringUtils.isNotEmpty(webUserVo.getOpenId())){
                map.put("openId", webUserVo.getOpenId());
            }
            String json = JSONObject.toJSONString(map);
            UsernamePhoneAuthenticationToken phoneAuthenticationToken = new UsernamePhoneAuthenticationToken(json);
            AuthenticationContextHolder.setContext(phoneAuthenticationToken);
            // 该方法会去调用UsernamePhoneUserDetailsServiceImpl.loadUserByUsername
            authentication = authenticationManager.authenticate(phoneAuthenticationToken);
        } catch (Exception e) {
            if (e instanceof BadCredentialsException) {
                throw new PhoneCodeNotMatchException();
            }
        } finally {
            AuthenticationContextHolder.clearContext();
        }
        //验证结束
        WebLoginUser webLoginUser = (WebLoginUser) authentication.getPrincipal();
        // 生成token
        String token = tokenService.createWebToken(webLoginUser);

        Map<String, Object> map = new HashMap<>(2);
        map.put("token", token);
        map.put("uid", webLoginUser.getUid());

        return AjaxResult.success(ResultEnum.LOGIN_SUCCESS.message, map);
    }
    /**
     * 校验手机登陆验证码
     * @param webUserVo
     */
    public void checkPhoneCode(WebUserInfoVo webUserVo){
        if(StringUtils.isEmpty(webUserVo.getPhone()) || StringUtils.isEmpty(webUserVo.getCode())){
            throw new BusinessException(ResultEnum.PARAM_ERROR);
        }
        String key = webUserVo.getPhone() + "_" + Constants.CODE;
        if(!redisCache.hasKey(key)){
            throw new BusinessException(ResultEnum.NOT_EXIST_PHONE_CODE);
        }
        String cacheCode = redisCache.getCacheObject(key).toString();
        if(!cacheCode.equals(webUserVo.getCode())){
            throw new BusinessException(ResultEnum.PHONE_CODE_ERROR);
        }

    }

}
